#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "fx0.h"

#ifdef  __cplusplus  
extern "C" {  
#endif 

/*
 * 暴露函数入口地址给其他语言环境下的调用函数
 */
C_DLL_EXP int   C_CALL int_add(int para1, int para2);
C_DLL_EXP char* C_CALL f_name_parse(char* string, int l_string);
C_DLL_EXP void  C_CALL f_name_free(char* real);
C_DLL_EXP void  C_CALL Scalars(double in, double *out);
C_DLL_EXP void  C_CALL OneDArray(int n, double anArray[]);
C_DLL_EXP void  C_CALL TwoDArray(int m, int n, double a2dArray[], int tda);
C_DLL_EXP void C_CALL TryComplex(Complex inputVar, Complex *outputVar,\
								                  int n, Complex array[]);
C_DLL_EXP void C_CALL MarshalStructC(marshalStruct *pointerinStruct);
C_DLL_EXP void C_CALL FreeMarshalStructptr(marshalStruct *pointerinStruct);
C_DLL_EXP void C_CALL EnumString(colour rainbow, char *rainbowcolour);
C_DLL_EXP void C_CALL CallBack(NAG_D01_FUN f, NAG_D01_FUN_PARA_T output);
C_DLL_EXP void C_CALL CallbackWithStruct(NAG_E04UCC_FUN funct , 
                                        int n, double *a, Nag_Comm *user_comm);

/**
  * @brief  整数加法
  * @Notes  None
  * @param  para1, 整数
  * @param  para1, 整数
  * @retval 和
  */
C_DLL_EXP int C_CALL int_add(int para1, int para2)
{
	int result = para1+para2;
	return result;
}

/**
  * @brief  双精度指针
  * @Notes  None
  * @param  in, 传入实数
  * @param  out, 返回实数指针
  * @retval None
  */
C_DLL_EXP void C_CALL Scalars(double in, double *out)
{
	*out = in;
}

/**
  * @brief  一维实数组
  * @Notes  None
  * @param  n, 数组元素数量
  * @param  anArray, 返回实数组
  * @retval None
  */
C_DLL_EXP void C_CALL OneDArray(int n, double anArray[])
{
	int i;
	for(i = 0; i < n; i++)
		anArray[i] = 77.7;
}

/**
  * @brief  二维实数组
  * @Notes  None
  * @param  m, 行数
  * @param  n, 列数
  * @param  a2dArray, 返回二维数组
  * @param  tda, 每行元素数量(列数)
  * @retval None
  */
#define A(I,J) 	a2dArray[I*tda+J]	
C_DLL_EXP void C_CALL TwoDArray(int m, int n, double a2dArray[], int tda)
{
  int i, j, k = 0;
  tda = n;
  for(i = 0; i < m; i++)
    for(j = 0; j < n; j++)
  	{
    	A(i,j) = ++k;
  	}
}

/**
  * @brief  结构体数组、结构体指针
  * @Notes  None
  * @param  inputVar, 结构体变量输入
  * @param  outputVar, 结构体变量指针(返回值)
  * @param  n, 结构体数组元素个数
  * @param  array, 结构体数组(双向参数: 输入、返回)
  * @retval None
  */
C_DLL_EXP void C_CALL TryComplex(Complex inputVar, Complex *outputVar,
								int n, Complex array[])
{
	outputVar->re = ++inputVar.re;
  outputVar->im = ++inputVar.im;

  	array[0].re = 99.0;
  	array[0].im = 98.0;
  	array[1].re = 97.0;
  	array[1].im = 96.0;
  
}

/**
  * @brief  结构体包含指针
  * @Notes  缓冲区内存空间动态分配与释放
  * @param  pointerinStruct, 结构体指针
  * @retval None
  */
C_DLL_EXP void C_CALL MarshalStructC(marshalStruct *pointerinStruct)
{
  int i;
  pointerinStruct->array = 
    (double *)malloc((size_t)(sizeof(double)*pointerinStruct->array_length));
  for (i = 0; i <pointerinStruct->array_length; i++)
    {
      pointerinStruct->array[i] = (double)(i)/10.0 + 1.0;
    }
}
C_DLL_EXP void C_CALL FreeMarshalStructptr(marshalStruct *pointerinStruct)
{
  free(pointerinStruct->array);
  pointerinStruct->array = 0;
}


/**
  * @brief  枚举+字符串处理
  * @Notes  缓冲区内存空间动态分配与释放
  * @param  pointerinStruct, 结构体指针
  * @retval None
  */
C_DLL_EXP void C_CALL EnumString(colour rainbow, char *rainbowcolour)
{
  if (rainbow == black )
    {
      strcpy(rainbowcolour, "Black is not a rainbow colour");
    }
  else
    {
      strcpy(rainbowcolour, "This is a rainbow colour");
    }
}


/**
  * @brief  函数指针
  * @Notes  回调函数
  * @param  f, 函数入口地址
  * @param  output, 返回参数值到被调函数
  * @retval None
  */
C_DLL_EXP void C_CALL CallBack(NAG_D01_FUN f, NAG_D01_FUN_PARA_T output)
{
  (*f)(output);
  *output = 20.18;
}


/**
  * @brief  使用结构体参数的函数指针
  * @Notes  回调函数
  * @param  funct, 函数入口地址
  * @param  n,a,user_comm, 被调函数的参数, 可返回参数值到被调函数
  * @retval None
  */
C_DLL_EXP void C_CALL CallbackWithStruct(NAG_E04UCC_FUN funct , 
                                        int n, double *a, Nag_Comm *user_comm)
{
  (*funct)(n, a, user_comm);
  if(user_comm->flag == 99)
  {
    user_comm->flag = 1;
    a[0] = 99.9;
  }
}

///////////////////////////////////////////////////////////////////
C_DLL_EXP char* C_CALL f_name_parse(char* string, int l_string)
{
	if(l_string < 1 || strlen(string) < 1 || string == NULL)
		return NULL;

	int l = l_string-1;
	char fn[64]; int j = 0;
	while(string[l] != '/'){ fn[j++] = string[l--]; }
	char* real = (char*)malloc(sizeof(char)*64);
	if(real == NULL)
		return NULL; 
	for(l = 0; l < j; l++){	real[l] = fn[j-1-l]; }
	return real;
}

C_DLL_EXP void C_CALL f_name_free(char* real)
{
	if(real != NULL)
		free(real);
}

#ifdef  __cplusplus  
}  
#endif  /* end of __cplusplus */ 